﻿/*************************************************************************************
 * 工    具：  HK_StopwatchSystem
 * 
 * 描    述：  HK_StopwatchSystem 是一个多功能倒计时管理系统，为开发者提供精确的时序控制能力，主要功能如下：
 *            通过可配置的倒计时实例，支持灵活的开始、暂停、恢复、重启等操作，满足复杂的时间管理需求。
 *            采用数据绑定机制实时反馈剩余时间，并通过事件驱动架构实现状态变更的自动化通知。
 * 
 * 版    本：  V1.1
 * 作    者：  京产肠饭
 * 
 * 创    建：  2025/03/11  V1.0
 *            
 * 更    新：  2025/06/18  V1.1
 *            1.代码优化：onCountdownEnd 回调添加空值检查
 *
 * 链   接：   https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System;
using System.Collections.Generic;
using QFramework;
using UnityEngine;

namespace HKTools
{
    public interface IHK_StopwatchSystem : ISystem
    {
        HK_Stopwatch CreateStopwatch(float time, Action onCountdownEnd);

        void CleanAllStopwatch();
    }

    public class HK_StopwatchSystem : AbstractSystem, IHK_StopwatchSystem
    {
        List<HK_Stopwatch> stopwatchesList;

        protected override void OnInit()
        {
            stopwatchesList = new List<HK_Stopwatch>();

            HKDebug.Log("IHK_StopwatchSystem 初始化完成!", LogColor.Cyan, LogStyle.Bold);
        }

        public HK_Stopwatch CreateStopwatch(float time, Action onCountdownEnd)
        {
            HK_Stopwatch stopwatch = new HK_Stopwatch(time, onCountdownEnd);

            stopwatchesList.Add(stopwatch);

            return stopwatch;
        }

        public void CleanAllStopwatch()
        {
            foreach (var stopwatch in stopwatchesList)
            {
                stopwatch.Stop();
            }

            stopwatchesList.Clear();
        }
    }

    public class HK_Stopwatch
    {
        // 倒计时总时间
        float totalTime;

        // 剩余时间
        public BindableProperty<float> RemainingTime;

        // 计时器是否正在运行
        public bool IsRunning { get; set; }
        // 计时器是否暂停
        bool isPause;

        // 倒计时结束事件
        public Action onCountdownEnd;

        // 新增委托引用字段
        Action updateAction;

        public HK_Stopwatch(float time, Action onCountdownEnd)
        {
            totalTime = time;
            this.onCountdownEnd = onCountdownEnd;

            RemainingTime = new BindableProperty<float>(totalTime);

            updateAction = OnCountDown;

            HKDebug.Log("倒计时创建成功", LogColor.Yellow);
        }

        // 开始倒计时
        public void Start()
        {
            if (IsRunning)
            {
                HKDebug.Log("计时器正在运行...", LogColor.Yellow);
                return;
            }

            RemainingTime.Value = totalTime;
            IsRunning = true;
            isPause = false;

            ActionKit.OnUpdate.Register(updateAction);

            HKDebug.Log("开始倒计时", LogColor.Yellow);
        }

        // 关闭计时器
        public void Stop()
        {
            if (!IsRunning)
            {
                HKDebug.Log("计时器未运行，无法关闭...", LogColor.Yellow);
                return;
            }

            RemainingTime.Value = totalTime;
            IsRunning = false;

            ActionKit.OnUpdate.UnRegister(updateAction);

            HKDebug.Log("关闭倒计时", LogColor.Yellow);
        }

        public void Pause()
        {
            if (!IsRunning)
            {
                HKDebug.Log("计时器未运行，无法暂停...", LogColor.Yellow);
                return;
            }

            isPause = true;
        }

        public void Resume()
        {
            if (!IsRunning)
            {
                HKDebug.Log("计时器未运行，无法恢复...", LogColor.Yellow);
                return;
            }

            isPause = false;
        }

        // 重置计时器
        public void Restart()
        {
            if (!IsRunning)
            {
                HKDebug.Log("计时器未运行，无法重置...", LogColor.Yellow);
                return;
            }

            RemainingTime.Value = totalTime;
            IsRunning = true;
            isPause = false;

            HKDebug.Log("重新开始计时器", LogColor.Yellow);
        }

        void OnCountDown()
        {
            if (IsRunning)
            {
                if (!isPause)
                {
                    // 减少当前时间
                    RemainingTime.Value -= Time.deltaTime;
                }

                if (RemainingTime.Value <= 0)
                {
                    // 倒计时结束
                    Stop();
                    // 触发倒计时结束事件，添加空值检查
                    onCountdownEnd?.Invoke();
                }
            }
        }
    }
}